/** 
 * @author Riccardo Manfrin [namesurname at gmail dot com]
 * 
 * @brief  Debug features for verbose output
 * 
 */
#include <stdlib.h>
#include <stdarg.h> /* handler for multiple arguments functions */
#include <unistd.h> /* sleep */
#include <string.h>
#include "debug.h"

typedef enum {
  INT,
  STR,
  CHR
} dbg_type;

typedef struct argnode{
  void *data;
  dbg_type t;
  struct argnode *next;
} arglist;

static char verbose = 0;

void dbg_verbose(int lev){
	verbose=lev;
}

unsigned int dbg_isverbose(int lev){
	if(verbose<lev) return 1;
	return 0;
}

void dbg_printf(int lev, const void *str, ...){
  if(dbg_isverbose(lev)){
    va_list ap;
    int lg=strlen((char*)str);
    arglist lst;
    arglist *lst_ptr = &lst;
    int lst_len = 0;
    int ctr;
    
    va_start(ap, str);
    
    for(ctr=0;ctr<lg;ctr++){
      if(((char*)str)[ctr]=='%')
      {
        switch(((char*)str)[ctr+1])
        {
          case 's':
          {
            lst_len++;
            lst_ptr->next = malloc(sizeof(arglist));
            memset(lst_ptr->next,0,sizeof(arglist));
            lst_ptr->next->t = STR;
            //Filling data
            lst_ptr->next->data = (char *) va_arg(ap, char *);
            
            lst_ptr=lst_ptr->next;
            break;
          }
          case 'c':
          {
            lst_len++;
            lst_ptr->next = malloc(sizeof(arglist));
            memset(lst_ptr->next,0,sizeof(arglist));
            lst_ptr->next->t = CHR;
            //Filling data
            lst_ptr->next->data = (char *) va_arg(ap, char *);
            lst_ptr=lst_ptr->next;
            break;
          }
          case 'i':
          {
            int t=0;
            lst_len++;
            lst_ptr->next = malloc(sizeof(arglist));
            memset(lst_ptr->next,0,sizeof(arglist));
            lst_ptr->next->t = INT;
            //Filling data
            lst_ptr->next->data = malloc(sizeof(int));
            t = va_arg(ap, int);
            memcpy(lst_ptr->next->data, &t,sizeof(int));
            lst_ptr=lst_ptr->next;
            break;
          }
          default:
          {
            break;
          }
        } // End of list setup
      }
    }
    ctr=0;
    lst_ptr=&lst;
    while(((char*)str)[ctr]!=0){
      if(((char*)str)[ctr]!='%')
      {
        printf("%c", ((char*)str)[ctr]);
      }
      else
      {
        switch(lst_ptr->next->t){
          case (INT):
          {
            printf("%i",*((int*)lst_ptr->next->data));
            ctr++;
            break;
          }
          case (STR):
          {
            printf("%s",(char*)lst_ptr->next->data);
            ctr++;
            break;
          }
          case (CHR):
          {
            printf("%c",*((char*)lst_ptr->next->data));
            ctr++;
            break;
          }
          default:
          {
            break;
          }
        }
        lst_ptr=lst_ptr->next;
      }
      ctr++;
    }
  }
  //sleep(1);
  return;
}
